package com.lambert.gingko.watermark.strategy;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import com.lambert.gingko.watermark.config.WatermarkProperties;
import com.lambert.gingko.watermark.model.WatermarkConfig;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * 抽象水印处理器
 * 所有水印处理器的基类，定义了水印处理器的基本行为
 * @author liubaolin
 * @since 2025/8/31 13:06
 */
@Slf4j
public abstract class AbstWatermarkProcessor implements WatermarkProcessor {

    @Resource
    protected WatermarkProperties properties;

    // 父类新增模板方法
    @Override
    public final File process(InputStream inputStream, String fileName, WatermarkConfig config) throws Exception {
        String extension = FileNameUtil.extName(fileName);
        File outputFile = FileUtil.createTempFile(getProcessorPrefix(), "." + extension, new File(properties.getTempDir()),false);
        try (InputStream is = inputStream) {
            // 子类实现具体处理逻辑
            doProcess(is, outputFile, extension, config);
        }
        return outputFile;
    }
    // 子类实现抽象方法
    protected abstract void doProcess(InputStream is, File outputFile , String extension, WatermarkConfig config) throws Exception;

    protected String getProcessorPrefix() {
        return "tmp_"+getSupportedType().name().toLowerCase();
    }

    /**
     * 颜色转16进制字符串
     */
    protected String toHexColor(Color color) {
        return String.format("#%02x%02x%02x",
                color.getRed(), color.getGreen(), color.getBlue());
    }

    /**
     * 将文本生成图片（返回字节数组，便于嵌入文档）
     */
    public static byte[] textToImage(WatermarkConfig config) throws IOException {
        // 1. 计算文本所需的画布大小
        Font font = config.getFont();
        String text = config.getText();

        // 虚拟画布计算文字宽高
        BufferedImage tempImage = new BufferedImage(1, 1, java.awt.image.BufferedImage.TYPE_INT_ARGB);
        Graphics2D tempG2d = tempImage.createGraphics();
        tempG2d.setFont(font);
        FontMetrics metrics = tempG2d.getFontMetrics();
        int textWidth = metrics.stringWidth(text);
        int textHeight = metrics.getHeight();
        tempG2d.dispose();

        // 2. 考虑旋转角度后的画布大小（避免文字被截断）
        double angleRadian = Math.toRadians(config.getAngle());
        int canvasWidth = (int) Math.ceil(
                Math.abs(textWidth * Math.cos(angleRadian)) +
                        Math.abs(textHeight * Math.sin(angleRadian))
        );
        int canvasHeight = (int) Math.ceil(
                Math.abs(textWidth * Math.sin(angleRadian)) +
                        Math.abs(textHeight * Math.cos(angleRadian))
        );

        // 3. 创建透明背景的图片
        BufferedImage image = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = image.createGraphics();

        // 设置抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 4. 设置透明度
        g2d.setComposite(AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER,
                config.getOpacity()
        ));

        // 5. 旋转画布（以中心为旋转点）
        g2d.translate(canvasWidth / 2.0, canvasHeight / 2.0);
        g2d.rotate(angleRadian);
        g2d.translate(-canvasWidth / 2.0, -canvasHeight / 2.0);

        // 6. 绘制文本（居中显示）
        g2d.setColor(config.getColor());
        g2d.setFont(font);
        int x = (canvasWidth - textWidth) / 2;
        int y = (canvasHeight + textHeight) / 2 - metrics.getDescent(); // 垂直居中
        g2d.drawString(text, x, y);

        g2d.dispose();

        // 7. 转换为字节数组（PNG格式，支持透明）
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos);
        return baos.toByteArray();
    }


    /**
     * 创建文字水印图片
     */
    protected BufferedImage createTextWatermarkImage(WatermarkConfig config) throws IOException {
        // 计算文字所需尺寸
        Font font = config.getFont();
        String text = config.getText();

        // 临时画布计算文字宽高
        BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        FontMetrics metrics = tempImage.createGraphics().getFontMetrics(font);
        int textWidth = metrics.stringWidth(text);
        int textHeight = metrics.getHeight();

        // 创建透明背景的水印图片
        BufferedImage watermarkImage = new BufferedImage(textWidth, textHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = initGraphics2D(watermarkImage); // 复用绘图配置

        // 设置颜色时确保Alpha通道正确
        g2d.setColor(config.getColor());
        g2d.setFont(font);
        // 绘制文字（y坐标使用ascent避免文字截断）
        g2d.drawString(text, 0, metrics.getAscent());
        g2d.dispose();
        return watermarkImage;
    }

    /**
     * 初始化绘图上下文（抗锯齿配置）
     * 优化点：提取重复配置逻辑，提高可维护性
     */
    protected Graphics2D initGraphics2D(BufferedImage image) {
        Graphics2D g = image.createGraphics();
        // 抗锯齿配置（提升文字/图像边缘清晰度）
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        return g;
    }
}
